#include "main.h"
#include <rtthread.h>
#include "bsp_lptime.h"

#ifdef RT_USING_PM

#define RCL_CLOCK						(32768)					/* 低速时钟频率32.768K*/	

/*Lptime config struct */
typedef struct 
{
	uint32_t 					lptime_periphs;	
	uint32_t 					lptime_prescaler; 
	IRQn_Type					lptime_irq;
	LPTIM_TypeDef *   lptimx;
}bsp_lptim_config_t;

static const bsp_lptim_config_t lptim_config_array[e_bsp_lptimmax] = {
	{LL_APB1_GRP1_PERIPH_LPTIM1, LL_LPTIM_PRESCALER_DIV32, LPTIM1_IRQn, LPTIM1},			//低功耗定时器1,分频系数为32
	{LL_APB1_GRP2_PERIPH_LPTIM2, LL_LPTIM_PRESCALER_DIV32, LPTIM2_IRQn, LPTIM2}				//低功耗定时器2,分频系数为32
};

static func_cb_void		lptim_cb[e_bsp_lptimmax] = {NULL};

/**
 ******************************************************************************
 ** @brief  LPTIMER1中断服务函数
 **
 ** @return 无
 ******************************************************************************/
void LPTIM1_IRQHandler(void)
{
   if (lptim_cb[e_bsp_lptim1] != NULL){
			 lptim_cb[e_bsp_lptim1]();
	 }
}

/**
 ******************************************************************************
 ** @brief  LPTIMER0中断服务函数
 **
 ** @return 无
 ******************************************************************************/
void LPTIM2_IRQHandler(void)
{
   if (lptim_cb[e_bsp_lptim1] != NULL){
			 lptim_cb[e_bsp_lptim2]();
	 }
}

/**
 ******************************************************************************
 ** @brief  初始化LPTIMER 为计数器功能,只能向上计数到0xFFFF(65535)
 **	@param  lptim_idx:低功耗定时器编号
 **         callback：中断回调函数
 ** @return TRUE/FALSE
 ******************************************************************************/
bool bsp_lptim_init(bsp_lptim_idx_e lptim_idx,  func_cb_void callback)
{
	uint32_t ltim_source;
	///< 使能LPTIM 外设时钟
	if (lptim_idx == e_bsp_lptim1){
			ltim_source = LL_RCC_LPTIM1_CLKSOURCE_LSE;
			LL_APB1_GRP1_EnableClock(lptim_config_array[lptim_idx].lptime_periphs);
	} else if (lptim_idx == e_bsp_lptim2) {
			ltim_source = LL_RCC_LPTIM2_CLKSOURCE_LSE;
			LL_APB1_GRP2_EnableClock(lptim_config_array[lptim_idx].lptime_periphs);
	} else {
		  return false;
	}
	/* 设置LPTIM的时钟 */
	LL_RCC_SetLPTIMClockSource(ltim_source);
	
  LL_LPTIM_SetClockSource(lptim_config_array[lptim_idx].lptimx, LL_LPTIM_CLK_SOURCE_INTERNAL);	
  LL_LPTIM_SetPrescaler(lptim_config_array[lptim_idx].lptimx, lptim_config_array[lptim_idx].lptime_prescaler);	
//	LL_LPTIM_ConfigTrigger(lptim_config_array[lptim_idx].lptimx, LPTIM_TRIGSOURCE_SOFTWARE);	
  LL_LPTIM_SetPolarity(lptim_config_array[lptim_idx].lptimx, LL_LPTIM_OUTPUT_POLARITY_REGULAR);	
  LL_LPTIM_SetUpdateMode(lptim_config_array[lptim_idx].lptimx, LL_LPTIM_UPDATE_MODE_IMMEDIATE);
  LL_LPTIM_SetCounterMode(lptim_config_array[lptim_idx].lptimx, LL_LPTIM_COUNTER_MODE_INTERNAL);

	/* LPTIM1 interrupt Init */
	NVIC_ClearPendingIRQ(lptim_config_array[lptim_idx].lptime_irq);
	NVIC_SetPriority(lptim_config_array[lptim_idx].lptime_irq, 0);
	NVIC_EnableIRQ(lptim_config_array[lptim_idx].lptime_irq);
	lptim_cb[lptim_idx] = callback;
	return true;
}

/**
 ******************************************************************************
 ** @brief  启动LPTIMER,只能向上计数到0xFFFF(65535)
 **	@param  lptim_idx:低功耗定时器编号
 **         period：计数周期
 **    period =  0xFFFF - arr + 0x0001
 ** 1. period = 1 ~ 65535, RCL = 32768,1分频时,周期可设置范围为 0.030ms~2000ms,默认使用RCL = 32768Hz
 ** 2. period = 1 ~ 65535, RCL = 38400,1分频时,周期可设置范围为 0.026ms~1706ms
 ** @return TRUE/FALSE
 ******************************************************************************/
bool bsp_lptime_start(bsp_lptim_idx_e lptim_idx, uint16_t period)
{	
	LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_32);																												 /* 1、使能外部中断32*/																								
	LL_LPTIM_EnableTimeout(lptim_config_array[lptim_idx].lptimx);																		 /* 2、使能超时 */
	LL_LPTIM_EnableIT_CMPM(lptim_config_array[lptim_idx].lptimx);																		 /* 3、使能CMPM中断 */
	LL_LPTIM_Enable(lptim_config_array[lptim_idx].lptimx);																					 /* 4、使能定时器 */
  LL_LPTIM_SetAutoReload(lptim_config_array[lptim_idx].lptimx, 0xFFFF);														 /* 5、配置Load the period value in the autoreload register*/
  LL_LPTIM_SetCompare(lptim_config_array[lptim_idx].lptimx, period);															 /* 6、配置Load the Timeout value in the compare register*/
  LL_LPTIM_StartCounter(lptim_config_array[lptim_idx].lptimx, LL_LPTIM_OPERATING_MODE_CONTINUOUS); /* 7、开启计时 Start timer in continuous mode */
	return true;
}

/**
 * @brief  This function stop lptime
 * @param  lptim_idx:低功耗定时器编号
 * @return TRUE/FALSE
 */
bool bsp_lptime_stop(bsp_lptim_idx_e lptim_idx)
{
	if (lptim_idx >= e_bsp_lptimmax){
			return false;
	}
	uint32_t _ier = lptim_config_array[lptim_idx].lptimx->IER;
	
	lptim_config_array[lptim_idx].lptimx->ICR = lptim_config_array[lptim_idx].lptimx->ISR & _ier;
	
	return true;
}

/**
 * @brief  This function get current count value of LPTIM
 * @param  lptim_idx:低功耗定时器编号
 * @return the count vlaue
 */
uint32_t bsp_lptim_get_current_tick(bsp_lptim_idx_e lptim_idx)
{
	if (lptim_idx >= e_bsp_lptimmax){
			return false;
	}
	return (LL_LPTIM_GetCounter(lptim_config_array[lptim_idx].lptimx));	
}

/**
 * @brief  This function get the count clock of LPTIM
 * @param  lptim_idx:低功耗定时器编号
 * @return the count clock frequency in Hz
 */
uint32_t bsp_lptim_get_countfreq(bsp_lptim_idx_e lptim_idx)
{
	uint8_t clock_prs;
	if (lptim_idx >= e_bsp_lptimmax){
			return false;
	}	
	switch(lptim_config_array[lptim_idx].lptime_prescaler){
	case LL_LPTIM_PRESCALER_DIV1:
			clock_prs = 1;
	break;
	
	case LL_LPTIM_PRESCALER_DIV2:
			clock_prs = 2;
	break;
	
	case LL_LPTIM_PRESCALER_DIV4:
			clock_prs = 4;
	break;
	
	case LL_LPTIM_PRESCALER_DIV8:
			clock_prs = 8;
	break;
	
	case LL_LPTIM_PRESCALER_DIV16:
			clock_prs = 16;
	break;
	
	case LL_LPTIM_PRESCALER_DIV32:
			clock_prs = 32;
	break;
	
	case LL_LPTIM_PRESCALER_DIV64:
			clock_prs = 64;
	break;
	
	case LL_LPTIM_PRESCALER_DIV128:
			clock_prs = 128;
	break;
	
	default:
	return false;
	}
	return (RCL_CLOCK / clock_prs);
}

/**
 * @brief  This function get the max value that LPTIM can count
 *
 * @return the max count
 */
uint32_t bsp_lptim_get_tick_max(void)
{
    return (0xFFFF);
}
/******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
#endif
